use actix_web::{http::StatusCode, HttpResponse, ResponseError};
use bcrypt::BcryptError;
use log::error;
use redis::RedisError;
use sea_orm::{DbErr, TransactionError};
use serde::Serialize;
use serde_json::json;
use std::{fmt, io};

#[derive(Debug, Serialize)]
pub enum ApiError {
    BadRequest(&'static str),
    Unauthorized(&'static str),
    Forbidden(&'static str),
    NotFound(&'static str),
    InternalServerError(&'static str),
}

impl ApiError {
    pub fn status_code(&self) -> StatusCode {
        match self {
            ApiError::BadRequest(_) => StatusCode::BAD_REQUEST,
            ApiError::Unauthorized(_) => StatusCode::UNAUTHORIZED,
            ApiError::Forbidden(_) => StatusCode::FORBIDDEN,
            ApiError::NotFound(_) => StatusCode::NOT_FOUND,
            ApiError::InternalServerError(_) => StatusCode::INTERNAL_SERVER_ERROR,
        }
    }

    pub fn business_code(&self) -> u16 {
        match self {
            ApiError::BadRequest(_) => 400,
            ApiError::Unauthorized(_) => 401,
            ApiError::Forbidden(_) => 403,
            ApiError::NotFound(_) => 404,
            ApiError::InternalServerError(_) => 500,
        }
    }

    pub fn message(&self) -> &str {
        match self {
            ApiError::BadRequest(msg) => msg,
            ApiError::Unauthorized(msg) => msg,
            ApiError::Forbidden(msg) => msg,
            ApiError::NotFound(msg) => msg,
            ApiError::InternalServerError(_) => "服务内部错误",
        }
    }
}

impl std::error::Error for ApiError {}

impl fmt::Display for ApiError {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        write!(f, "{}", self.message())
    }
}

impl From<DbErr> for ApiError {
    fn from(err: DbErr) -> Self {
        error!("Database error: {:?}", err);
        ApiError::InternalServerError("Database error occurred")
    }
}

impl From<RedisError> for ApiError {
    fn from(err: RedisError) -> Self {
        error!("Redis error: {:?}", err);
        ApiError::InternalServerError("Redis error occurred")
    }
}

impl From<serde_json::Error> for ApiError {
    fn from(err: serde_json::Error) -> Self {
        error!("Json error: {:?}", err);
        ApiError::InternalServerError("JSON parsing error")
    }
}

impl From<BcryptError> for ApiError {
    fn from(err: BcryptError) -> Self {
        error!("Bcrypt error: {:?}", err);
        ApiError::InternalServerError("Password hashing error")
    }
}

impl From<regex::Error> for ApiError {
    fn from(err: regex::Error) -> Self {
        error!("Regex error: {:?}", err);
        ApiError::InternalServerError("Regex error occurred")
    }
}

impl From<io::Error> for ApiError {
    fn from(err: io::Error) -> Self {
        error!("IO error: {:?}", err);
        ApiError::InternalServerError("IO error occurred")
    }
}

impl From<TransactionError<ApiError>> for ApiError {
    fn from(err: TransactionError<ApiError>) -> Self {
        match err {
            TransactionError::Transaction(err) => err,
            TransactionError::Connection(err) => {
                error!("Transaction error: {:?}", err);
                ApiError::InternalServerError("Transaction error occurred")
            }
        }
    }
}

impl ResponseError for ApiError {
    fn error_response(&self) -> HttpResponse {
        let json = json!({
            "message": self.message(),
            "status": self.business_code(),
        });
        HttpResponse::build(self.status_code()).json(json)
    }
}
